home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / segment.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  9KB  |  386 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9.  
  10. #define GEN
  11.  
  12. #include "hdr.h"
  13. #include "vars.h"
  14. #include "gvars.h"
  15. #include "type.h"
  16. #include "segment.h"
  17. #include "miscp.h"
  18. #include "dbxp.h"
  19. #include "axqrp.h"
  20. #include "gmiscp.h"
  21. #include "segmentp.h"
  22.  
  23. static void segment_put_n(Segment, int, int, char *);
  24. static void segment_realloc(Segment, unsigned);
  25.  
  26. extern Segment    CODE_SEGMENT, DATA_SEGMENT, DATA_SEGMENT_MAIN;
  27.  
  28. #ifdef MACHINE_CODE
  29. void print_data_segment()                                /*;print_data_segment*/
  30. {
  31.     Segment    seg;
  32.     char        line[250], c;
  33.     int        i, w, *sp;
  34.  
  35.     seg = DATA_SEGMENT; 
  36.     sp = (int *) seg->seg_data;
  37.     to_gen(" ");
  38.     to_gen_int("--- Global data segment # ", CURRENT_DATA_SEGMENT);
  39.     for (i = 0; i < seg->seg_maxpos; i++) {
  40.         w = *sp++;
  41.         if (w >= ' ' && w <= '~') c = w; 
  42.         else c = ' ';
  43.         sprintf(line, "     %5d  %8x %c %d", i, w, c, w);
  44.         to_gen(line);
  45.     }
  46. }
  47. #endif
  48.  
  49. void segment_append(Segment s, Segment sa)                    /*;segment_append*/
  50. {
  51.     /* append segment sa at end of segment s */
  52.  
  53.     int    i, la;
  54.  
  55.     seg_check(s);
  56.     if (s->seg_kind != SEGMENT_KIND_DATA)
  57.         chaos("segment_append not appending a data segment");
  58.     s->seg_pos = s->seg_maxpos;
  59.     la = sa->seg_maxpos;
  60.     for (i = 0; i < la; i++) {
  61.         segment_put_int(s, ((int *)(sa->seg_data))[i]);
  62.     }
  63. }
  64.  
  65. void seg_check(Segment seg)                                        /*;seg_check*/
  66. {
  67.     if (seg->seg_id != SEG_ID)
  68.         chaos("invalid segment - check word invalid ");
  69. }
  70.  
  71. void segment_empty(Segment s)                                /*;segment_empty*/
  72. {
  73.     /* seg segment to empty state, but do no reallocate it */
  74.     seg_check(s);
  75.     s->seg_pos = 0;
  76.     s->seg_maxpos = 0;
  77. }
  78.  
  79. void segment_free(Segment s)                                /*;segment_free*/
  80. {
  81.     seg_check(s);
  82.     efreet(s->seg_data, "segment-data");
  83.     efreet((char *) s, "segment");
  84. }
  85.  
  86. int segment_get_int(Segment s, int i)                    /*;segment_get_int*/
  87. {
  88.     /* get value of word from location i in segment seg. */
  89.  
  90.     int    *resp;
  91.  
  92.     seg_check(s);
  93.     if (i >= s->seg_maxpos) {
  94.         chaos("segment.c: get_int retrieving from undefined location\n");
  95.         return 0;
  96.     }
  97.     if (s->seg_kind == SEGMENT_KIND_DATA) {
  98.         resp = (int *) s->seg_data + i;
  99.         return *resp;
  100.     }
  101.     else {
  102. #ifdef ALIGN_WORD
  103.         /* retrieve byte by byte to avoid alignment problems */
  104.         register int j;
  105.         int v;
  106.         register char *sp, *tp;
  107.  
  108.         resp = (int *) (s->seg_data + i);
  109.         sp = (char *) resp;
  110.         tp = (char *) &v;
  111.         for (j = 0; j < sizeof(int); j++) *tp++ = *sp++;
  112.         return v;
  113. #else
  114.         resp = (int *) (s->seg_data + i);
  115.         return *resp;
  116. #endif
  117.     }
  118. }
  119.  
  120. unsigned int segment_get_pos(Segment seg)                /*;segment_get_pos*/
  121. {
  122.     seg_check(seg);
  123.     return seg->seg_pos;
  124. }
  125.  
  126. unsigned int segment_get_maxpos(Segment seg)            /*;segment_get_maxpos*/
  127. {
  128.     seg_check(seg);
  129.     return seg->seg_maxpos;
  130. }
  131.  
  132. int segment_get_off(Segment s, int i)                        /*;segment_get_off*/
  133. {
  134.     return segment_get_int(s, i);
  135. }
  136.  
  137. void segment_put_byte(Segment s, int v)                    /*;segment_put_byte*/
  138. {
  139.     unsigned    newpos, pos;
  140.  
  141.     seg_check(s);
  142.  
  143.     if (s->seg_kind != SEGMENT_KIND_CODE)
  144.         chaos("segment.c: segment_put_byte called on data segment");
  145.  
  146.     pos = s->seg_pos;
  147.     newpos = pos + 1;
  148.     if (newpos >= s->seg_dim) {
  149.         segment_realloc(s, newpos);
  150.     }
  151.     s->seg_data[pos] = (char) v;
  152.     s->seg_pos = newpos;
  153.     if (s->seg_maxpos < newpos) s->seg_maxpos = newpos;
  154. }
  155.  
  156. void segment_put_const(Segment seg, Const con)            /*;segment_put_const*/
  157. {
  158.     if (con->const_kind == CONST_INT) {
  159.         /* can safely put integers - defer others for later */
  160.         segment_put_word(seg, INTV(con));
  161.     }
  162.     else if(con->const_kind == CONST_REAL) {
  163.         segment_put_real(seg, REALV(con));
  164.     }
  165.     else if(con->const_kind == CONST_FIXED) {
  166.         segment_put_long(seg, FIXEDV(con));
  167.     }
  168.     else {
  169. #ifdef DEBUG
  170.         zpcon(con);
  171. #endif
  172.         chaos("segment.c - meaningless kind of literal");
  173.     }
  174. }
  175.  
  176. void segment_put_int(Segment s, int v)                        /*;segment_put_int*/
  177. {
  178.     unsigned    newpos, pos;
  179.     int        *d;
  180.  
  181.     seg_check(s);
  182.     pos = s->seg_pos;
  183.     if (s->seg_kind == SEGMENT_KIND_DATA) {
  184.         newpos = pos + 1;
  185.         if (newpos >= s->seg_dim)
  186.             segment_realloc(s, newpos);
  187.         d = (int *) s->seg_data;
  188.         d[pos] = v;
  189.     }
  190.     else { /* if code segment */
  191.         newpos = pos + sizeof(int);
  192.         if (newpos >= s->seg_dim)
  193.             segment_realloc(s, newpos);
  194. #ifdef ALIGN_WORD
  195.         /* if must worry about alignment, do byte by byte */
  196.         {
  197.             int iv;
  198.             iv = v;
  199.             (void) segment_put_n(s, s->seg_pos, sizeof(int), (char *) &iv);
  200.         }
  201. #else
  202.         d = (int *) (s->seg_data + pos);
  203.         *d = v;
  204. #endif
  205.     }
  206.     s->seg_pos = newpos;
  207.     if (s->seg_maxpos < newpos) s->seg_maxpos = newpos;
  208. }
  209.  
  210. void segment_put_long(Segment s, long v)                /*;segment_put_long*/
  211. {
  212.     long    lv = v;
  213.     segment_put_n(s, s->seg_pos, sizeof(long), (char *) &lv);
  214. }
  215.  
  216. static void segment_put_n(Segment s, int i, int n, char *p)    /*;segment_put_n*/
  217. {
  218.     /* put n bytes from p at location i in segment seg, extending
  219.      * segment if necessary 
  220.      */
  221.  
  222.     unsigned    newpos, pos;
  223.     int        *d;
  224.     char    *dc;
  225.  
  226.     seg_check(s);
  227.     segment_set_pos(s, (unsigned) i, 0);
  228.     pos = s->seg_pos;
  229.     if (s->seg_size == 1) { /* if code segment */
  230.         newpos = pos + n;
  231.         if (newpos >= s->seg_dim)
  232.             segment_realloc(s, newpos);
  233.         dc = s->seg_data + pos;
  234.         while (n--)
  235.             *dc++ = *p++;
  236.     }
  237.     else { /* assume word size */
  238.         newpos = pos + n/sizeof(int);
  239.         if (newpos >= s->seg_dim)
  240.             segment_realloc(s, newpos);
  241.         d = (int *)( s->seg_data) + pos;
  242.         dc = (char *) d;
  243.         while (n--)
  244.             *dc++ = (unsigned char) *p++;
  245.     }
  246.     s->seg_pos = newpos;
  247.     if (s->seg_maxpos < newpos) s->seg_maxpos = newpos;
  248. }
  249.  
  250. void segment_put_off(Segment s, int i, int v)                /*;segment_put_off*/
  251. {
  252.     /* put value of v, interpreted as offset (16 bits) at location i
  253.      * in segment seg.
  254.      * We assume this is used to overwrite a previously defined location
  255.      * and raise chaos if this is not the case.
  256.      */
  257.  
  258.     unsigned    pos, oldpos;
  259.     int        *d;
  260.  
  261.     seg_check(s);
  262.  
  263.     if (i >= s->seg_maxpos)
  264.         chaos("segment.c: segment_put_off of undefined location");
  265.  
  266.     pos = i;
  267.     if (s->seg_kind == SEGMENT_KIND_DATA) {
  268.         d = (int *) s->seg_data;
  269.         d[pos] = v;
  270.     }
  271.     else {
  272. #ifdef ALIGN_WORD
  273.         {  
  274.             int iv; 
  275.             iv = v;
  276.             oldpos = s->seg_pos; /* save pos since segment_put_n may alter it */
  277.             segment_put_n(s, i, sizeof(int), (char *)&iv);
  278.             s->seg_pos = oldpos;
  279.         }
  280. #else
  281.         d = (int *) (s->seg_data + pos);
  282.         *d = v;
  283. #endif
  284.     }
  285. }
  286.  
  287. void segment_put_real(Segment s, double db)                /*;segment_put_real*/
  288. {
  289.     float    r = db;
  290.     segment_put_n(s, s->seg_pos, sizeof(float), (char *) &r);
  291. }
  292.  
  293. void segment_put_ref(Segment seg, int segnum, int off)        /*;segment_put_ref*/
  294. {
  295.     if (seg->seg_kind == SEGMENT_KIND_DATA) {
  296.         segment_put_int(seg, segnum);
  297.         segment_put_int(seg, off);
  298.     }
  299.     else {
  300.         segment_put_byte(seg, segnum);
  301.         segment_put_int(seg, off);
  302.     }
  303. }
  304.  
  305. void segment_put_word(Segment s, int v)                    /*;segment_put_word*/
  306. {
  307.     segment_put_int(s, v);
  308. }
  309.  
  310. void segment_set_pos(Segment s, unsigned pos, unsigned offtyp)
  311.                                                         /*;segment_set_pos*/
  312. {
  313.     /* set position of segment to offset pos. offtyp is type of offset,
  314.      * interpreted similarly to lseek(2); i.e., offtyp is 0 for offset
  315.      * from start of segment, 1 for offset from current position, and 2
  316.      * for offset from end of segment. Only the cases 0 and 2 are supported now.
  317.      */
  318.  
  319.     seg_check(s);
  320.     if (offtyp == 2) { /* to position at end ignore pos */
  321.         s->seg_pos = s->seg_maxpos;
  322.         return;
  323.     }
  324.     if (offtyp != 0)
  325.         chaos("segment_set_pos bad offset type");
  326.     s->seg_pos = pos;
  327. }
  328.  
  329. static void segment_realloc(Segment s, unsigned newdim)        /*;segment_realloc*/
  330. {
  331.     /* extend dimension field if necessary to it is at least as large
  332.      * as newdim
  333.      */
  334.  
  335.     unsigned    incr, dim;
  336.  
  337.     seg_check(s);
  338.     dim = s->seg_dim;
  339.     if (dim >= newdim) return;
  340.     incr = newdim - dim;
  341.     if (incr < s->seg_extend) incr = s->seg_extend;
  342.     s->seg_dim += incr;
  343.     s->seg_data = erealloct(s->seg_data, s->seg_dim * s->seg_size,
  344.       "segment-realloc");
  345.     /* update ptr to data if one is being kept */
  346.     if (s->seg_ptr != (int **) 0) {
  347.         *(s->seg_ptr) = (int *) s->seg_data;
  348.     }
  349. }
  350.  
  351. Segment template_new(int t_kind, int t_size, int words, int **ptr)
  352.                                                             /*;template_new*/
  353. {
  354.     Segment    s;
  355.  
  356.     s = segment_new(SEGMENT_KIND_DATA, words);
  357.     s->seg_ptr = ptr; /* save address of pointer to be updated */
  358.     /* return pointer to start of segment */
  359.     *(s->seg_ptr) = (int *) s->seg_data;
  360.     segment_put_word(s, t_kind);
  361.     segment_put_word(s, t_size);
  362.     /* assume user will fill in rest direcly so point to end */
  363.     s->seg_pos = s->seg_maxpos = words;
  364.     return s;
  365. }
  366.  
  367. unsigned int PC()                                                        /*;PC*/
  368. {
  369.     /* corresponds to macro PC in SETL version */
  370.  
  371.     seg_check(CODE_SEGMENT);
  372.     return CODE_SEGMENT->seg_maxpos;
  373. }
  374.  
  375. #ifdef DEBUG
  376. void zpseg(Segment seg)                                                /*;zpseg*/
  377. {
  378.     printf("Segment %d x%x ", (int)seg, seg);
  379.     if (seg->seg_kind == SEGMENT_KIND_CODE) printf(" code");
  380.     else printf(" data");
  381.     printf(" size %d pos %d max_pos %d dim %d ext %d\n", seg->seg_size,
  382.         seg->seg_pos, seg->seg_maxpos, seg->seg_dim, seg->seg_extend);
  383.     /* should print part of data here */
  384. }
  385. #endif
  386.